package com.oinux.playhelper.service;

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import android.app.ActivityManager;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.Binder;
import android.os.Debug;
import android.os.IBinder;
import android.util.Log;

import com.j256.ormlite.android.apptools.OrmLiteBaseService;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.QueryBuilder;
import com.oinux.playhelper.app.AppContext;
import com.oinux.playhelper.db.DatabaseHelper;
import com.oinux.playhelper.entity.AppInfo;
import com.oinux.playhelper.entity.AppStat;
import com.oinux.playhelper.util.TimeUtils;

public class MainService extends OrmLiteBaseService<DatabaseHelper> {

	private static final String TAG = "boot_service";

	private IBinder binder = new MainService.LocalBinder();
	private Timer refreshTimer;
	private Timer countTimer;
	private AppContext appContext;

	@Override
	public IBinder onBind(Intent intent) {
		return binder;
	}

	@Override
	public void onCreate() {
		super.onCreate();
		Log.v(TAG, "onCreate.");
		appContext = (AppContext) getApplication();
		refreshTimer = new Timer();
		refreshTimer.scheduleAtFixedRate(new TimerTask() {

			@Override
			public void run() {
				refreshApps();
			}
		}, 0L, 1000 * 60L);
		Calendar calendar = Calendar.getInstance();
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		countTimer = new Timer();
		countTimer.schedule(new TimerTask() {

			@Override
			public void run() {
				appContext.count();
			}
		}, calendar.getTime(), TimeUtils.DIVIDE_TO_DAY);
	}

	@Override
	public void onStart(Intent intent, int startId) {
		Log.v(TAG, "onStart.");
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.v(TAG, "服务已启动.");
		loadApps();
		return START_STICKY;
	}

	@Override
	public void onDestroy() {
		if (refreshTimer != null) {
			refreshTimer.cancel();
		}
		if (countTimer != null) {
			countTimer.cancel();
		}
		startService(new Intent(this, MainService.class));
	}
	
	public void loadApps() {
		Log.v(TAG, "载入app状态");
		List<PackageInfo> packages = getPackageManager()
				.getInstalledPackages(0);
		try {
			Dao<AppInfo, Integer> appInfoDao = getHelper().getAppInfoDao();
			for (int i = 0; i < packages.size(); i++) {
				PackageInfo packageInfo = packages.get(i);
				if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
					AppInfo appInfo = null;
					List<AppInfo> appInfos = appInfoDao.queryForEq(
							"packageName", packageInfo.packageName);
					if (appInfos.size() == 0) {
						appInfo = new AppInfo();
						appInfo.setInstall(true);
						appInfo.setIcon(packageInfo.applicationInfo
								.loadIcon(getPackageManager()));
						appInfo.setPackageName(packageInfo.packageName);
						appInfo.setName(packageInfo.applicationInfo.loadLabel(
								getPackageManager()).toString());
						appInfo.setProcessName(packageInfo.applicationInfo.processName);
					} else {
						appInfo = appInfos.get(0);
					}
					if (appInfos.size() == 0) {
						appInfoDao.create(appInfo);
					} else {
						appInfoDao.update(appInfo);
					}
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public void refreshApps() {
		Log.v(TAG, "更新app状态");
		try {
			ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
			List<ActivityManager.RunningAppProcessInfo> processInfos = activityManager
					.getRunningAppProcesses();
			Dao<AppInfo, Integer> appInfoDao = getHelper().getAppInfoDao();
			Dao<AppStat, Integer> appStatDao = getHelper().getAppStatDao();
			List<AppInfo> appInfoList = appInfoDao.queryForAll();
			if (appInfoList.size() != 0) {
				Date now = new Date();
				for (AppInfo appInfo : appInfoList) {
					boolean isRunning = false;
					QueryBuilder<AppStat, Integer> queryBuilder = appStatDao
							.queryBuilder();
					queryBuilder.orderBy("id", false).where()
							.eq("appInfo_id", appInfo.getId()).and()
							.isNull("finishTime").and().isNotNull("startTime");
					PreparedQuery<AppStat> preparedQuery = queryBuilder
							.prepare();
					AppStat appStat = appStatDao.queryForFirst(preparedQuery);
					for (ActivityManager.RunningAppProcessInfo appProcessInfo : processInfos) {
						if (appInfo.getProcessName().equals(
								appProcessInfo.processName)) {
							isRunning = true;
							if (appStat == null) {
								appStat = new AppStat();
								appStat.setStartTime(now);
								appStat.setAppInfo(appInfo);
								appStatDao.create(appStat);
							}
							appInfo.setPid(appProcessInfo.pid);
							appInfo.setUid(appProcessInfo.uid);
							int[] pids = new int[] { appInfo.getPid() };
							Debug.MemoryInfo[] memoryInfo = activityManager
									.getProcessMemoryInfo(pids);
							int memSize = memoryInfo[0].dalvikPrivateDirty;
							appInfo.setMemSize(memSize);
							break;
						}
					}
					if (appStat != null) {
						if (appInfo.isRunning()) {
							appInfo.setRunTime(now.getTime()
									- appStat.getStartTime().getTime());
							if (!isRunning) {
								appInfo.setTotalTime(appInfo.getTotalTime()
										+ appInfo.getRunTime());
								appInfo.setRunTime(0);
								appInfo.setMemSize(0);
								appStat.setFinishTime(now);
								appStatDao.update(appStat);
							}
						}
					}
					appInfo.setRunning(isRunning);
					appInfoDao.update(appInfo);
				}
			} else {
				loadApps();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	public class LocalBinder extends Binder {
		MainService getService() {
			return MainService.this;
		}
	}
}